using System.Xml.Linq;
using DynamicData.Kernel;
using TailBlazer.Domain.Infrastructure;
using TailBlazer.Domain.Settings;

namespace TailBlazer.Domain.Formatting;

public class GeneralOptionsConverter: IConverter<GeneralOptions>
{
    private static class Structure
    {
        public const string Root = "Root";
        public const string Theme = "Theme";
        public const string HighlightTail = "HighlightTail";
        public const string Duration = "Duration";
        public const string Scale = "Scale";
        public const string Rating = "FrameRate";
        public const string OpenRecentOnStartup = "OpenRecentOnStartup";
        public const string ShowLineNumbers = "ShowLineNumbers";
    }

    public GeneralOptions Convert(State state)
    {
        var defaults = GetDefaultValue();
        if (state== State.Empty) return defaults;

        var doc = XDocument.Parse(state.Value);
        var root = doc.ElementOrThrow(Structure.Root);
        var theme = root.ElementOrThrow(Structure.Theme).ParseEnum<Theme>().ValueOr(()=> defaults.Theme);
        var highlight = root.ElementOrThrow(Structure.HighlightTail).ParseBool().ValueOr(() => defaults.HighlightTail);
        var duration = root.ElementOrThrow(Structure.Duration).ParseDouble().ValueOr(()=>defaults.HighlightDuration);
        var scale = root.ElementOrThrow(Structure.Scale).ParseDouble().ValueOr(()=>defaults.Scale);
        var frameRate = root.OptionalElement(Structure.Rating).ConvertOr(rate=>rate.ParseInt().Value, () => defaults.Rating);
        var openRecent = root.ElementOrThrow(Structure.OpenRecentOnStartup).ParseBool().ValueOr(() => defaults.OpenRecentOnStartup);
        var showLineNumbers = root.OptionalElement(Structure.ShowLineNumbers).ConvertOr(x => x.ParseBool().Value, () => defaults.ShowLineNumbers);

        return new GeneralOptions(theme,highlight, duration,scale, frameRate, openRecent, showLineNumbers);
    }

    public State Convert(GeneralOptions options)
    {
        var root = new XElement(new XElement(Structure.Root));
        root.Add(new XElement(Structure.Theme, options.Theme));
        root.Add(new XElement(Structure.HighlightTail, options.HighlightTail));
        root.Add(new XElement(Structure.Duration, options.HighlightDuration));
        root.Add(new XElement(Structure.Scale, options.Scale));
        root.Add(new XElement(Structure.Rating, options.Rating));
        root.Add(new XElement(Structure.OpenRecentOnStartup, options.OpenRecentOnStartup));
        root.Add(new XElement(Structure.ShowLineNumbers, options.ShowLineNumbers));
        var doc = new XDocument(root);
        var value= doc.ToString();
        return new State(1, value);
    }

    public GeneralOptions GetDefaultValue()
    {
        return new GeneralOptions(Theme.Dark, true, 5, 100, 5, true, false);
    }
}